﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestBullet : MonoBehaviour
{
    [System.Serializable]
    public class BulletPositionPair
    {
        public Vector3 Position = Vector3.zero;

        public Vector3 Direction = Vector3.right;

        public float Angle = 0f;
    }

    public enum BulletType
    {
        None = 0,
        C,
        M,
        S,
        F,
        L,
        R,
    }

    public GameObject boom;
    public float speed = 500;
    public float damage = 1;
    public float hitDistance = 20;
    public BulletType type = BulletType.None;
    public bool playerBullet = false;

    [Header("调试")]
    public bool bulletR = false;

    protected Vector3 launchPosition = Vector3.zero;
    protected bool launched;

    protected Rigidbody rig;

    protected GameObject source;
    protected BulletType bulletType;
    protected Vector3 direction;

    public bool isBulletR()
    {
        return bulletR;
    }
    public void SetBulletR(bool r)
    {
        this.bulletR = r;
    }
    public BulletType GetBulletType()
    {
        return bulletType;
    }
    public void SetBulletType(BulletType bulletType)
    {
        this.bulletType = bulletType;
    }
    public void SetSource(GameObject source)
    {
        this.source = source;
    }
    public GameObject GetSource()
    {
        return this.source;
    }


    protected void CommonHit(Vector3 position, GameObject target)
    {
        float damageResult = DamageTarget(target);
        if (damageResult >= 0)
        {
            this.damage -= damageResult;
            if (this.damage <= 0)
            {
                CreateBoom(position);
                rig.velocity = Vector3.zero;
                Destroy(gameObject);
            }
        }
        else
        {
            CreateBoom(position);
            rig.velocity = Vector3.zero;
            Destroy(gameObject);
        }
    }
    protected void CommonFly()
    {
        if (launched)
        {
            Vector3 currentPosition = transform.position;
            if ((currentPosition - launchPosition).magnitude > hitDistance)
            {
                //Disappear();
            }
        }
    }

    protected void CommonLaunch(Vector3 direction)
    {
        this.direction = direction;
        Vector3 force = direction * (speed * (bulletR ? 1.5f : 1f));
        rig.AddForce(force);
        launchPosition = transform.position;
        launched = true;
    }
    protected void CommonOnDestroy()
    {
    }

    public static BulletPositionPair[] LaunchBulletPosition(BulletType bulletType, Vector3 originPosition, Vector3 direction)
    {
        BulletPositionPair[] ret;
        switch (bulletType)
        {
            case BulletType.S:
                float gapArg = 12f;
                int bulletCount = 5;//(int)(360/gapArg)
                ret = new BulletPositionPair[bulletCount];
                float roatArg = (ret.Length - 1) / 2f * gapArg;
                for (int i = 0; i < ret.Length; i++)
                {
                    float arg = gapArg * i - roatArg;
                    float argRad = arg * Mathf.Deg2Rad;
                    float x = direction.x * Mathf.Cos(argRad) + direction.y * Mathf.Sin(argRad);
                    float y = -direction.x * Mathf.Sin(argRad) + direction.y * Mathf.Cos(argRad);
                    ret[i] = new BulletPositionPair()
                    {
                        Position = originPosition,
                        Direction = new Vector3(x, y)
                    };

                }
                break;
            case BulletType.L:
                Vector3 cross = Vector3.Cross(Vector3.right, direction);
                float angle = Vector3.Angle(Vector3.right, direction);
                angle *= cross.z;
                int count = 4;
                int offset = -4;
                Ray2D ray = new(originPosition, direction);
                ret = new BulletPositionPair[count];
                for (int i = offset; i < offset + count; i++)
                {
                    int index = i - offset;
                    Vector3 pos = ray.GetPoint(i);
                    ret[index] = new BulletPositionPair()
                    {
                        Position = pos,
                        Direction = direction,
                        Angle = angle
                    };
                }
                break;
            default:
                ret = new BulletPositionPair[]{
                 new BulletPositionPair()
                    {
                        Position = originPosition,
                        Direction = direction
                    }
                };
                break;

        }
        return ret;

    }

    protected void Disappear()
    {
        Destroy(gameObject);
    }

    protected GameObject CreateBoom(Vector3 position)
    {
        return Instantiate(boom, position, Quaternion.identity);
    }

    protected float DamageTarget(GameObject target)
    {
        float ret = -1;
        if (target != null)
        {
            Damageable damageable = target.GetComponent<Damageable>();
            if (damageable != null)
            {
                ret = damageable.Damage(source, this.damage);
            }
        }
        return ret;
    }

    private static Dictionary<BulletType, ISet<GameObject>> _BULLET_SET = new();
    public static void AddBullet(BulletType type, GameObject bullet)
    {
        ISet<GameObject> hashSet = _BULLET_SET.GetValueOrDefault(type, null);
        if (hashSet == null)
        {
            hashSet = new HashSet<GameObject>();
            _BULLET_SET.Add(type, hashSet);
        }
        hashSet.Add(bullet);
    }
    public static bool RemoveBullet(BulletType type, GameObject bullet)
    {
        ISet<GameObject> hashSet = _BULLET_SET.GetValueOrDefault(type, null);
        if (hashSet == null)
        {
            hashSet = new HashSet<GameObject>();
            _BULLET_SET.Add(type, hashSet);
        }
        return hashSet.Remove(bullet);
    }
    public static ISet<GameObject> GetBulletSet(BulletType type)
    {
        ISet<GameObject> ret = new HashSet<GameObject>();
        ISet<GameObject> hashSet = _BULLET_SET.GetValueOrDefault(type, null);
        if (hashSet != null)
        {
            ret.UnionWith(hashSet);
        }
        return ret;
    }
    public static void ClearBulletSet(BulletType type)
    {
        ISet<GameObject> hashSet = _BULLET_SET.GetValueOrDefault(type, null);
        if (hashSet != null)
        {
            hashSet.Clear();
        }
    }
    private void Awake()
    {
        gameObject.SetActive(false);
        rig = GetComponent<Rigidbody>();
    }
    void Start()
    {
    }

    // Update is called once per frame
    void Update()
    {
        CommonFly();
    }
    private void FixedUpdate()
    {
    }

    private void OnDestroy()
    {
        this.CommonOnDestroy();
    }
    public void Launch(Vector3 direction)
    {
        gameObject.SetActive(true);
        CommonLaunch(direction);
    }

    protected void Hit(GameObject target)
    {
        this.CommonHit(transform.position, target);
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        GameObject target = collision.gameObject;
        //string layerName=LayerMask.LayerToName(target.layer);

        Hit(target);

        //if (this.enemyLayerNames.IndexOf(layerName) >= 0)
        //{
        //    Hit(target);
        //}else if (this.blockLayerNames.IndexOf(layerName) >= 0)
        //{
        //    Hit(target);
        //}
    }
}
